/*
 * Copyright (c) 2022  by Junzhao
 * THIS FILE IS PART OF JAVASE Song Huongkang PROJECT
 * All Rights Reserved.
 */

package lambda表达式;

import org.junit.Test;

import java.util.Comparator;
import java.util.function.Consumer;

/**
 * @Description Lambda表达式
 * 是一个 匿名函数 ，我们可以把 Lambda 表达式理解为是 一段可以
 * 传递的代码 （将代码像数据一样进行传递）。使用它可以写出更简洁、更
 * 灵活的代码。作为一种更紧凑的代码风格，使 Java 的语言表达能力得到了提升。
 * <p>
 * Lambda表达式 在 Java 8 语言中引入 的 一 种 新的语法元素和操
 * 作符。这个操作符为 “ -> ” 该操作符被称为 Lambda 操作符或 箭头操作符。
 * 它将 Lambda 分为两个部分：
 * 左侧：指定了 Lambda 表达式需要的参数列表(其实就是接口中抽象方法的形参列表)
 * 右侧：指定了 Lambda体 是抽象方法的实现逻辑（方法体），也即Lambda 表达式要执行的功能。
 * <p>
 * 本质就是接口的一个实例（区别于Python等语言）
 * @Author 俊昭
 * @Date 2022/5/11
 */
public class lambdaTest {
    @Test
    public void test002() {
        // 格式 一 : 无参 无返回值
        Runnable r2 = () -> {
            for (int i = 0; i < 5; i++) {
                System.out.print(i + "\t");
            }
        };
        r2.run();
        System.out.println("\n***************");
        // 格式 二 : 一个参数 无返回值
//        Consumer<String> c1 = new Consumer<String>() {
//            @Override
//            public void accept(String s) {
//                System.out.println(s);
//            }
//        };
//        Consumer<String> c1 = System.out::println; 方法引用形式
        Consumer<String> c1 = (String s) -> {
            System.out.println(s);
        };
        c1.accept("你好1");


        System.out.println("\n***************");
        // 格式 三 : 数据类型可以省略 可由编译器推断得出
        Consumer<String> c2 = (s) -> {
            System.out.println(s);
        };
        c2.accept("你好2");

        // 上述Lambda 表达式中的参数类型都是由编译器推断得出的。 Lambda
        // 表达式中无需指定类型，程序依然可以编译，这是因为 javac 根据程序
        // 的上下文，在后台推断出了参数的类型。 Lambda 表达式的类型依赖于
        // 上下文环境，是由编译器推断出来的。这就是所谓的 “类型推断
        // 数组声明 int[] arr = (new int[]){...} 圆括号内是类型推断
        // 集合声明 ArrayList<String> list = new ArrayList<>(); 这里的第二个尖括号是类型推断

        System.out.println("\n***************");
        // 格式 四 : 只要一个参数 小括号可以省略
        Consumer<String> c3 = s -> {
            System.out.println(s);
        };
        c3.accept("你好3");

        System.out.println("\n***************");
        // 格式 五 : Lambda 需要两个或以上的参数，多条执行语句，并且可以有返回值
        Comparator<Integer> c4 = (o1, o2) -> {
            System.out.println(o1);
            System.out.println(o2);
            return  o1 > o2 ? 1 : 0;
        };

        System.out.println(c4.compare(21, 12));

        System.out.println("\n***************");
        // 格式 六 : 当 Lambda 体只有 一条 语句时， return 与大括号 若有，都可以省略

        Comparator<Integer> c5 = (o1, o2) -> o1 > o2 ? 1 : 0;

        System.out.println(c5.compare(2, 1));

        Consumer<String> c6 = s -> System.out.println(s);
        c6.accept("你好4");




    }

    @Test
    public void test001() {
        // 使用匿名对象
        Runnable r1 = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    System.out.print(i + "\t");
                }
            }
        };

        r1.run();
        System.out.println("\n***************");

        // 使用lambda表达式

        Runnable r2 = () -> {
            for (int i = 0; i < 5; i++) {
                System.out.print(i + "\t");
            }
        };

        r2.run();
        System.out.println("\n***************");

        // 匿名对象
        Comparator<Integer> c1 = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return (o1 > o2) ? 1 : 0;
            }
        };
        // 语法糖（Syntactic sugar），也译为糖衣语法，
        // 是由英国计算机科学家彼得·约翰·兰达（Peter J. Landin）发明的一个术语，
        // 指计算机语言中添加的某种语法，这种语法对语言的功能并没有影响，但是更方便程序员使用。
        // 通常来说使用语法糖能够增加程序的可读性，从而减少程序代码出错的机会。

        System.out.println(c1.compare(2, 1));


        //lambda
        Comparator<Integer> c2 = (o1, o2) -> (o1 > o2) ? 1 : 0;

        System.out.println(c2.compare(2, 1));

        // 完全是等价的！

        // 还可以这样！ 使用方法引用！
        Comparator<Integer> c3 = Integer::compare;

        System.out.println(c3.compare(2, 1));


    }
}
